using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wombat.Core;
using Wombat.Core.Services;
using Wombat.Data.Model;
using Wombat.Data.Model.Dtos;
using Wombat.Data.Model.Factories;
using Tag = Wombat.Data.Model.Tag;

namespace Wombat.Data
{
    public class DataService : IDataService, IInitializable
    {
        private readonly IEntitiesFactory _factory;
        private readonly ITagFactory _tagFactory;
        private readonly TaskFactory _taskFactory = new TaskFactory();


        public DataService(IEntitiesFactory factory, ITagFactory tagFactory)
        {
            _factory = factory;
            _tagFactory = tagFactory;
        }

        public string ConnectionString { get; set; }

        public async Task InsertFloatDataAsync(FloatData data)
        {
            await _taskFactory.StartNew(() =>
                              {
                                  using (var db = _factory.Create())
                                  {
                                      db.FloatDatas.AddObject(data);
                                      db.SaveChanges();
                                  }
                              }
                );
        }

        public void InsertFloatData(FloatData data)
        {
            using (var db = _factory.Create())
            {
                db.FloatDatas.AddObject(data);
                db.SaveChanges();
            }
        }

        public void BulkInsertFloatData(IEnumerable<FloatData> queueFloat)
        {
            throw new System.NotImplementedException();
        }

        public async Task<IEnumerable<CodeTagDto>> GetCodeTagsAsync(Func<IQueryable<Tag>, IQueryable<Tag>> filter = null)
        {
            return await _taskFactory.StartNew(() =>
                                      {
                                          using (var db = _factory.Create())
                                          {
                                              var allTags = db.Tags
                                                  .Include("Unit")
                                                  .Where(t => t.Type == (int)TagType.Code);
                                              var filteredTags = filter != null ? filter(allTags) : allTags;
                                              return filteredTags.ToList().Select(t => _tagFactory.CreateCodeTag(t));
                                          }
                                      });
        }

        public async Task<IEnumerable<Core.Tag>> GetAllTagsAsync()
        {
            return await _taskFactory.StartNew(() =>
                {
                    using (var db = _factory.Create())
                    {
                        return db.Tags
                                 .ToList()
                                 .Select(t => new Core.Tag
                                     {
                                         Name = t.Name,
                                         PersistedId = t.Id,
                                         UniqueId = t.Guid
                                         ,
                                         DataStreamType = TagDataStreamType.Continues,
                                         DataType = typeof(double?)
                                     });
                    }
                });
        }

        public void Initialize()
        {
            var initializable = _factory as IInitializable;
            if (initializable != null) initializable.Initialize();
        }
    }
}